﻿using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Collections.Generic;
using System.Text;

namespace smcrypto
{
    public class SM4Utils
    {
        public String secretKey = "";
        public String iv = "";
        public bool hexString = false;
        public bool isPadding = true;

        public String Encrypt_CBC(String plainText)
        {
            return Encrypt_CBC(plainText, Encoding.Default);
        }

        public String Encrypt_CBC(String plainText,Encoding encoding)
        {
            SM4_Context ctx = new SM4_Context();
            ctx.isPadding = isPadding;
            ctx.mode = SM4.SM4_ENCRYPT;

            byte[] keyBytes;
            byte[] ivBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
                ivBytes = Hex.Decode(iv);
            }
            else
            {
                keyBytes = encoding.GetBytes(secretKey);
                ivBytes = encoding.GetBytes(iv);
            }

            SM4 sm4 = new SM4();
            sm4.sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, encoding.GetBytes(plainText));

            String cipherText = encoding.GetString(Hex.Encode(encrypted));
            return cipherText;
        }

        public String Encrypt_ECB(String plainText)
        {
            return Encrypt_ECB(plainText, Encoding.Default);
        }


        public String Encrypt_ECB(String plainText, Encoding encoding)
        {
            SM4_Context ctx = new SM4_Context();
            ctx.isPadding = isPadding;
            ctx.mode = SM4.SM4_ENCRYPT;

            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = encoding.GetBytes(secretKey);
            }

            SM4 sm4 = new SM4();
            sm4.sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.sm4_crypt_ecb(ctx, encoding.GetBytes(plainText));
            String cipherText = encoding.GetString(Hex.Encode(encrypted));
            return cipherText;
        }

        public byte[] Encrypt_ECB(byte[] plainBytes)
        {
            return Encrypt_ECB(plainBytes, Encoding.Default);
        }


        public byte[] Encrypt_ECB(byte[] plainBytes, Encoding encoding)
        {
            SM4_Context ctx = new SM4_Context();
            ctx.isPadding = isPadding;
            ctx.mode = SM4.SM4_ENCRYPT;
            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = encoding.GetBytes(secretKey);
            }
            SM4 sm4 = new SM4();
            sm4.sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.sm4_crypt_ecb(ctx, plainBytes);
            return encrypted;

            //return Hex.Encode(encrypted);
        }

        public String Decrypt_ECB(String cipherText)
        {
            return Decrypt_ECB(cipherText, Encoding.Default);
        }


        public String Decrypt_ECB(String cipherText, Encoding encoding)
        {
            SM4_Context ctx = new SM4_Context();
            ctx.isPadding = isPadding;
            ctx.mode = SM4.SM4_DECRYPT;

            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = encoding.GetBytes(secretKey);
            }

            SM4 sm4 = new SM4();
            sm4.sm4_setkey_dec(ctx, keyBytes);
            byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Hex.Decode(cipherText));
            return encoding.GetString(decrypted);
        }
        public byte[] Decryp_ECB(String cipherText)
        {
            return Decryp_ECB(cipherText, Encoding.Default);
        }

        public byte [] Decryp_ECB(String cipherText, Encoding encoding)
        {
            SM4_Context ctx = new SM4_Context();
            ctx.isPadding = isPadding;
            ctx.mode = SM4.SM4_DECRYPT;

            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = encoding.GetBytes(secretKey);
            }

            SM4 sm4 = new SM4();
            sm4.sm4_setkey_dec(ctx, keyBytes);
            byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Hex.Decode(cipherText));
            return decrypted;
        }

        public byte[] Decryp_ECB(byte[] cipherText)
        {
            return Decryp_ECB(cipherText, Encoding.Default);
        }

        public byte[] Decryp_ECB(byte[] cipherText, Encoding encoding)
        {
            SM4_Context ctx = new SM4_Context();
            ctx.isPadding = isPadding;
            ctx.mode = SM4.SM4_DECRYPT;

            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = encoding.GetBytes(secretKey);
            }

            SM4 sm4 = new SM4();
            sm4.sm4_setkey_dec(ctx, keyBytes);
            byte[] decrypted = sm4.sm4_crypt_ecb(ctx, cipherText);
            return decrypted;
        }
        public string Decrypt_CBC(String cipherText)
        {
            return Decrypt_CBC(cipherText, Encoding.Default);
        }

        public String Decrypt_CBC(String cipherText, Encoding encoding)
        {
            SM4_Context ctx = new SM4_Context();
            ctx.isPadding = isPadding;
            ctx.mode = SM4.SM4_DECRYPT;

            byte[] keyBytes;
            byte[] ivBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
                ivBytes = Hex.Decode(iv);
            }
            else
            {
                keyBytes = encoding.GetBytes(secretKey);
                ivBytes = encoding.GetBytes(iv);
            }

            SM4 sm4 = new SM4();
            sm4.sm4_setkey_dec(ctx, keyBytes);
            byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Hex.Decode(cipherText));
            return encoding.GetString(decrypted);
        }
    }
}